/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package etherblocks.engine.states;

import java.util.ArrayList;
import com.jme3.app.Application;
import com.jme3.app.state.AppStateManager;
import com.jme3.collision.CollisionResult;
import com.jme3.collision.CollisionResults;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import etherblocks.engine.network.*;
import etherblocks.game.entitysystem.*;
import etherblocks.game.entitysystem.systems.*;

/**
 *
 * @author Carl
 */
public class EntitySystemAppState extends BaseAppState{

    public EntitySystemAppState(){
        
    }
    private EntityMap entityMap;
    private Node entitiesNode;
    private ArrayList<EntitySystem> entitySystems = new ArrayList<EntitySystem>();

    @Override
    public void initialize(AppStateManager stateManager, Application application){
        super.initialize(stateManager, application);
        entitiesNode = new Node("entities");
        mainApplication.getRootNode().attachChild(entitiesNode);
        addEntitySystem(new RemoveEntitySystem(entitiesNode));
        addEntitySystem(new ModelSystem(entitiesNode));
        addEntitySystem(new AnimationSystem(entitiesNode));
        addEntitySystem(new PhysicsSystem(entitiesNode, mainApplication.getStateManager()));
        NetworkClient networkClient = getAppState(NetworkAppState.class).getNetworkClient();
        if(networkClient.isServer()){
            NetworkServer networkServer = (NetworkServer) networkClient;
            entityMap = networkServer.getGameServer().getWorld().getEntityMap();
            addEntitySystem(new PhysicsTransformSystem_Server(entitiesNode, networkClient.getGameClient().getPlayerEntityID()));
            addEntitySystem(new PhysicsUpdateSystem(entitiesNode));
        }
        else{
            entityMap = networkClient.getGameClient().getEntityMap();
            addEntitySystem(new PhysicsTransformSystem_Client(entitiesNode, networkClient.getGameClient().getPlayerEntityID()));
        }
    }
    
    public void addEntitySystem(EntitySystem entitySystem){
        entitySystems.add(entitySystem);
    }

    @Override
    public void update(float lastTimePerFrame){
        super.update(lastTimePerFrame);
        for(int i=0;i<entitySystems.size();i++){
            EntitySystem entitySystem = entitySystems.get(i);
            entitySystem.onNextFrameCalculation(entityMap, lastTimePerFrame);
        }
    }

    public Spatial getSpatial(int entityID){
        return ModelObjectSystem.getModelObject(entitiesNode, entityID);
    }
    
    public Entity getTargetedEntity(){
        int playerEntityID = getAppState(NetworkAppState.class).getNetworkClient().getGameClient().getPlayerEntityID();
        CollisionResults rayCastingResults = mainApplication.getRayCastingResults(mainApplication.getRootNode());
        for(int i=0;i<rayCastingResults.size();i++){
            CollisionResult collisionResult = rayCastingResults.getCollision(i);
            Entity entity = getAppState(EntitySystemAppState.class).getEntity(collisionResult.getGeometry());
            if(entity != null){
                if(entity.getID() != playerEntityID){
                    return entity;
                }
            }
            else{
                return null;
            }
        }
        return null;
    }

    public Entity getEntity(Spatial spatial){
        while(spatial != null){
            if((spatial.getName() != null) && (spatial.getName().startsWith("entity_"))){
                int id = Integer.parseInt(spatial.getName().substring("entity_".length()));
                return new Entity(entityMap, id);
            }
            spatial = spatial.getParent();
        }
        return null;
    }

    public EntityMap getEntityMap(){
        return entityMap;
    }

    public Node getEntitiesNode(){
        return entitiesNode;
    }
}
